package com.atguigu.tingshu.search.service.impl;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregate;
import co.elastic.clients.elasticsearch._types.aggregations.LongTermsBucket;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.NestedQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.CompletionSuggestOption;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.Suggestion;
import co.elastic.clients.json.JsonData;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.album.client.AlbumInfoFeignClient;
import com.atguigu.tingshu.album.client.CategoryFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.PinYinUtils;
import com.atguigu.tingshu.model.album.*;
import com.atguigu.tingshu.model.search.AlbumInfoIndex;
import com.atguigu.tingshu.model.search.AttributeValueIndex;
import com.atguigu.tingshu.model.search.SuggestIndex;
import com.atguigu.tingshu.query.search.AlbumIndexQuery;
import com.atguigu.tingshu.search.repository.AlbumIndexRepository;
import com.atguigu.tingshu.search.repository.SuggestIndexRepository;
import com.atguigu.tingshu.search.service.SearchService;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.search.AlbumInfoIndexVo;
import com.atguigu.tingshu.vo.search.AlbumSearchResponseVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.suggest.Completion;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;


@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class SearchServiceImpl implements SearchService {

    @Autowired
    private AlbumInfoFeignClient albumInfoFeignClient;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

    @Autowired
    private CategoryFeignClient categoryFeignClient;

    @Autowired
    private AlbumIndexRepository albumIndexRepository;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private ElasticsearchClient elasticsearchClient;

    @Autowired
    private SuggestIndexRepository suggestIndexRepository;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;
    @Override
    public List<AlbumInfoIndex> findRankingList(Long category1Id, String dimension) {
        //  hget key field;
        return (List<AlbumInfoIndex>) redisTemplate.opsForHash().get(RedisConstant.RANKING_KEY_PREFIX+category1Id,dimension);
    }

    @Override
    public void updateLatelyAlbumRanking() {
        //  获取分类Id数据
        Result<List<BaseCategory1>> baseCategory1Result = categoryFeignClient.findAllCategory1();
        //  判断
        Assert.notNull(baseCategory1Result,"一级分类集合为空");
        List<BaseCategory1> baseCategory1List = baseCategory1Result.getData();
        Assert.notNull(baseCategory1List,"一级分类数据为空");
        //  循环遍历.
        for (BaseCategory1 baseCategory1 : baseCategory1List) {
            //  一个分类下有五个维度
            //  Hash数据结构： hset key field value;  key=category1Id field = 热度/播放量/订阅量/购买量/评论数 value=热度data/播放量data;
            String[] rankingDimensionArray = new String[]{"hotScore", "playStatNum", "subscribeStatNum", "buyStatNum", "commentStatNum"};
            //  循环遍历
            for (String ranking : rankingDimensionArray) {
                //  1。  执行dsl语句 获取数据！
                SearchRequest.Builder searchRequestBuilder = new SearchRequest.Builder();
                //  根据分类Id 进行过滤数据
                searchRequestBuilder.index("albuminfo").query(q->q.term(t->t.field("category1Id").value(baseCategory1.getId())))
                        .sort(s->s.field(f->f.field(ranking).order(SortOrder.Desc)))
                        .size(10);
                //  执行方法
                SearchResponse<AlbumInfoIndex> searchResponse = null;
                try {
                    //  获取到返回结果集
                    searchResponse = elasticsearchClient.search(searchRequestBuilder.build(), AlbumInfoIndex.class);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                //  获取查询的结果集
                List<AlbumInfoIndex> infoIndexList = searchResponse.hits().hits().stream().map(Hit::source).collect(Collectors.toList());

                //                List<AlbumInfoIndex> albumInfoIndexList = searchResponse.hits().hits().stream().map(hit -> {
                //                    AlbumInfoIndex albumInfoIndex = hit.source();
                //                    return albumInfoIndex;
                //                }).collect(Collectors.toList());
                //  将执行的结果集放入缓存： redis 使用那种数据类型来存储排行榜数据：hash hset key field value
                String rangKey = RedisConstant.RANKING_KEY_PREFIX+baseCategory1.getId();
                //  保存数据到缓存。
                this.redisTemplate.opsForHash().put(rangKey,ranking,infoIndexList);
            }
        }
    }

    @Override
    public List<String> completeSuggest(String keyword) {
        //  1. 先准备dsl 语句
        SearchRequest.Builder searchRequestBuilder = new SearchRequest.Builder();
        //  准备dsl
        searchRequestBuilder.index("suggestinfo")
                .suggest(s->s.suggesters("suggestionKeyword",
                        f->f.prefix(keyword).completion(
                                c->c.field("keyword")
                                        .skipDuplicates(true)
                                        .size(10)
                                        .fuzzy(z->z.fuzziness("auto"))))
                        .suggesters("suggestionkeywordPinyin",
                                f->f.prefix(keyword).completion(
                                        c->c.field("keywordPinyin")
                                                .skipDuplicates(true)
                                                .size(10)
                                                .fuzzy(z->z.fuzziness("auto"))))
                        .suggesters("suggestionkeywordSequence",
                                f->f.prefix(keyword).completion(
                                        c->c.field("keywordSequence")
                                                .skipDuplicates(true)
                                                .size(10)
                                                .fuzzy(z->z.fuzziness("auto"))))
                );
        //  执行dsl语句并获取到结果集.
        SearchResponse<SuggestIndex> searchResponse = null;
        try {
            searchResponse = elasticsearchClient.search(searchRequestBuilder.build(), SuggestIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //  获取结果集 Set 无序不重复.
        HashSet<String> titleSet = new HashSet<>();
        titleSet.addAll(this.parseResultData(searchResponse,"suggestionKeyword"));
        titleSet.addAll(this.parseResultData(searchResponse,"suggestionkeywordPinyin"));
        titleSet.addAll(this.parseResultData(searchResponse,"suggestionkeywordSequence"));
        //  判断
        if (titleSet.size()<10){
            //  不够10条记录。需要查询专辑/提词库信息记录补充到10条记录为止！
            SearchResponse<SuggestIndex> response = null;
            try {
                response = elasticsearchClient.search(f -> f.index("suggestinfo")
                                .query(q -> q.match(m -> m.field("title").query(keyword)))
                        , SuggestIndex.class);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            //  获取检索的结果集
            List<Hit<SuggestIndex>> hits = response.hits().hits();
            //  循环遍历
            for (Hit<SuggestIndex> hit : hits) {
                //  获取到提词对象
                SuggestIndex suggestIndex = hit.source();
                //  获取到提词标题
                String title = suggestIndex.getTitle();
                //  将标题添加到集合中
                titleSet.add(title);
                //  判断集合长度
                if (titleSet.size()==10){
                    break;
                }
            }
        }
        //  返回List集合。
        return new ArrayList<>(titleSet);
    }

    /**
     * 根据key来获取结果集.
     * @param searchResponse
     * @param keyword
     * @return
     */
    private List<String> parseResultData(SearchResponse<SuggestIndex> searchResponse, String keyword) {
        //  获取到集合数据
        List<Suggestion<SuggestIndex>> suggestionsList = searchResponse.suggest().get(keyword);
        Suggestion<SuggestIndex> suggestIndexSuggestion = suggestionsList.get(0);
        //  获取集合数据
        List<CompletionSuggestOption<SuggestIndex>> suggestOptionList = suggestIndexSuggestion.completion().options();
        /*for (CompletionSuggestOption<SuggestIndex> option : suggestOptionList) {
            //  获取提词对象
            SuggestIndex suggestIndex = option.source();
            String title = suggestIndex.getTitle();
        }*/
        List<String> list = suggestOptionList.stream().map(option -> {
            SuggestIndex suggestIndex = option.source();
            return suggestIndex.getTitle();
        }).collect(Collectors.toList());
        //  返回集合数据
        return list;
    }

    @Override
    public List<Map<String, Object>> channel(Long category1Id) {
        //  创建一个集合对象
        List<Map<String, Object>> mapList = new ArrayList<>();
        //  1.  先获取一级分类下的三级分类集合数据.
        Result<List<BaseCategory3>> baseCategory3List = categoryFeignClient.findTopBaseCategory3(category1Id);
        Assert.notNull(baseCategory3List, "返回三级分类集合为空");
        List<BaseCategory3> category3List = baseCategory3List.getData();
        Assert.notNull(category3List, "三级分类集合为空");

        //  将这个集合 baseCategory3List 转换为map key=category3Id value = BaseCategory3;
        Map<Long, BaseCategory3> category3IdToMap = category3List.stream().collect(Collectors.toMap(BaseCategory3::getId, baseCategory3 -> baseCategory3));

        //  2.  构建DSL语句.
        //  获取到三级分类Id 集合 1001 1002 1003 1004 1005 1006 1007
        List<Long> category3IdList = category3List.stream().map(BaseCategory3::getId).collect(Collectors.toList());
        //  进行数据类型专辑 List<FieldValue>
        List<FieldValue> category3IdValueList = category3IdList.stream().map(category3Id -> FieldValue.of(category3Id)).collect(Collectors.toList());
        //  创建查询对象 根据一级分类Id 下的三级分类Id 查询数据
        SearchRequest.Builder searchRequestBuilder = new SearchRequest.Builder();
        searchRequestBuilder.index("albuminfo").query(q -> q.terms(t -> t.field("category3Id").terms(
                f -> f.value(category3IdValueList)
        )));
        //  按照三级分类Id 进行分组. 获取前6条数据记录.
        searchRequestBuilder.aggregations("groupByCategory3IdAgg", f -> f.terms(t -> t.field("category3Id").size(10))
                .aggregations("topTenHotScoreAgg", a -> a.topHits(t -> t.size(6).sort(s -> s.field(o -> o.field("hotScore").order(SortOrder.Desc)))))
        );
        //  声明对象
        SearchResponse<AlbumInfoIndex> searchResponse = null;
        try {
            searchResponse = elasticsearchClient.search(searchRequestBuilder.build(), AlbumInfoIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        Aggregate aggregate = searchResponse.aggregations().get("groupByCategory3IdAgg");
        //  循环遍历
        for (LongTermsBucket groupByCategory3IdAgg : aggregate.lterms().buckets().array()) {
            //  获取到三级分类Id
            long category3Id = groupByCategory3IdAgg.key();
            //  创建一个list 集合对象来存储数据 AlbumInfoIndex
            List<AlbumInfoIndex> list = new ArrayList<>();
            //  获取三级分类Id 内部数据
            Aggregate topTenHotScoreAgg = groupByCategory3IdAgg.aggregations().get("topTenHotScoreAgg");
            for (Hit<JsonData> hit : topTenHotScoreAgg.topHits().hits().hits()) {
                //  获取到数据
                String jsonData = hit.source().toString();
                //  数据类型转换. AlbumInfoIndex
                AlbumInfoIndex albumInfoIndex = JSONObject.parseObject(jsonData, AlbumInfoIndex.class);
                //  将这个对象albumInfoIndex添加到集合中
                list.add(albumInfoIndex);
            }
            //  需要声明一个map 集合
            Map<String,Object> map = new HashMap<>();
            //  存储三级分类Id 对象
            map.put("baseCategory3",category3IdToMap.get(category3Id));
            //  前6条专辑信息
            map.put("list",list);
            //  将map 添加到集合中.
            mapList.add(map);
        }
        //  返回数据
        return mapList;
    }

    @Override
    public AlbumSearchResponseVo search(AlbumIndexQuery albumIndexQuery) {

        //  本质：给这个对象属性赋值：
        /*
        private List<AlbumInfoIndexVo> list = new ArrayList<>(); -- es 获取傲的集合数据hits._source
        private Long total;//总记录数
        private Integer pageSize;//每页显示的条数
        private Integer pageNo;//当前页面
        private Long totalPages;
         */
        //  1.  先生成一个dsl 语句
        SearchRequest searchRequest = this.queryBuildDsl(albumIndexQuery);
        //  2.  执行检索 第一个参数：SearchRquest 第二个参数：返回的数据类型
        SearchResponse<AlbumInfoIndex> searchResponse = null;
        try {
            searchResponse = elasticsearchClient.search(searchRequest, AlbumInfoIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //  创建一个对象 在这个方法中只赋值 List<AlbumInfoIndexVo> list 属性
        AlbumSearchResponseVo albumSearchResponseVo = this.parseResultData(searchResponse);
        //  赋值总记录数
        albumSearchResponseVo.setTotal(searchResponse.hits().total().value());
        albumSearchResponseVo.setPageSize(albumIndexQuery.getPageSize());
        albumSearchResponseVo.setPageNo(albumIndexQuery.getPageNo());
        //  10 3 4     9 3 3
        //  int totalPages = albumSearchResponseVo.getTotal()%albumIndexQuery.getPageSize()==0?albumSearchResponseVo.getTotal()/albumIndexQuery.getPageSize():albumSearchResponseVo.getTotal()/albumIndexQuery.getPageSize()+1;
        long totalPages = (albumSearchResponseVo.getTotal() + albumIndexQuery.getPageSize() - 1) / albumIndexQuery.getPageSize();
        albumSearchResponseVo.setTotalPages(totalPages);
        return albumSearchResponseVo;
    }


    private AlbumSearchResponseVo parseResultData(SearchResponse<AlbumInfoIndex> searchResponse) {
        //  此时这个方法只需要给  List<AlbumInfoIndexVo> list 赋值：
        AlbumSearchResponseVo albumSearchResponseVo = new AlbumSearchResponseVo();
        //  从searchResponse 对象中获取到hit 集合对象
        List<Hit<AlbumInfoIndex>> hits = searchResponse.hits().hits();
        //  声明一个对象来存储索引库的集合
        //        List<AlbumInfoIndexVo> list = new ArrayList<>();
        //        for (Hit<AlbumInfoIndex> hit : hits) {
        //            //  获取到专辑索引库对象
        //            AlbumInfoIndex albumInfoIndex = hit.source();
        //            AlbumInfoIndexVo albumInfoIndexVo = new AlbumInfoIndexVo();
        //            //  属性拷贝：
        //            BeanUtils.copyProperties(albumInfoIndex,albumInfoIndexVo);
        //            list.add(albumInfoIndexVo);
        //        }
        List<AlbumInfoIndexVo> list = hits.stream().map(hit -> {
            //  根据_source 获取到 albumInfoIndex 对象
            AlbumInfoIndex albumInfoIndex = hit.source();
            //  创建对象
            AlbumInfoIndexVo albumInfoIndexVo = new AlbumInfoIndexVo();
            //  属性拷贝：
            BeanUtils.copyProperties(albumInfoIndex, albumInfoIndexVo);
            //  判断：用户是否通过关键词进行检索，如果是通过关键词则title 需要高亮.
            if (null != hit.highlight().get("albumTitle")) {
                //  获取到高亮的专辑标题
                String albumTitle = hit.highlight().get("albumTitle").get(0);
                //  将高亮字段放入对象中.
                albumInfoIndexVo.setAlbumTitle(albumTitle);
            }
            //  返回数据：
            return albumInfoIndexVo;
        }).collect(Collectors.toList());

        //   List<AlbumInfoIndexVo> list
        albumSearchResponseVo.setList(list);
        //  返回数据
        return albumSearchResponseVo;
    }

    private SearchRequest queryBuildDsl(AlbumIndexQuery albumIndexQuery) {
        //  用户可能输入的检索条件有哪些? 关键词
        SearchRequest.Builder searchRequest = new SearchRequest.Builder();
        //  创建Query 对象
        //  Query.Builder query = new Query.Builder();
        //  创建一个Bool 对象
        BoolQuery.Builder boolQuery = new BoolQuery.Builder();
        //  从哪个索引库查询数据
        searchRequest.index("albuminfo");
        //  关键词必须存在.
        if (!StringUtils.isEmpty(albumIndexQuery.getKeyword())) {
            boolQuery.should(s -> s.match(m -> m.field("albumTitle").query(albumIndexQuery.getKeyword())));
            boolQuery.should(s -> s.match(m -> m.field("albumIntro").query(albumIndexQuery.getKeyword())));
            //  设置高亮显示！
            searchRequest.highlight(f -> f.fields("albumTitle", h -> h.preTags("<span style=color:red>").postTags("</span>")));
        }

        //  判断是否根据分类Id 进行检索
        if (!StringUtils.isEmpty(albumIndexQuery.getCategory1Id())) {
            boolQuery.filter(f -> f.term(t -> t.field("category1Id").value(albumIndexQuery.getCategory1Id())));
        }
        if (!StringUtils.isEmpty(albumIndexQuery.getCategory2Id())) {
            boolQuery.filter(f -> f.term(t -> t.field("category2Id").value(albumIndexQuery.getCategory2Id())));
        }
        if (!StringUtils.isEmpty(albumIndexQuery.getCategory3Id())) {
            boolQuery.filter(f -> f.term(t -> t.field("category3Id").value(albumIndexQuery.getCategory3Id())));
        }
        //  赋值
        searchRequest.query(q -> q.bool(boolQuery.build()));
        //  先获取到属性Id 与属性值Id 集合数据
        List<String> attributeList = albumIndexQuery.getAttributeList();
        if (!CollectionUtils.isEmpty(attributeList)) {
            //  循环遍历 属性id:属性值id  1:15
            for (String attribute : attributeList) {
                //  分割字符串
                String[] split = attribute.split(":");
                //  判断数组
                if (null != split && split.length == 2) {
                    //  构建嵌套查询
                    NestedQuery nestedQuery = NestedQuery.of(f -> f.path("attributeValueIndexList")
                            .query(q -> q.bool(b -> b.filter(f1 -> f1.term(t -> t.field("attributeValueIndexList.attributeId").value(split[0])))
                                    .filter(f1 -> f1.term(t -> t.field("attributeValueIndexList.valueId").value(split[1])))
                            )));
                    //  boolQuery.filter(nestedQuery.query());
                    boolQuery.filter(f -> f.nested(nestedQuery));
                }
            }
        }
        //  排序：先获取到排序规则 排序（综合排序[1:desc] 播放量[2:desc] 发布时间[3:desc]；asc:升序 desc:降序）
        String order = albumIndexQuery.getOrder();
        if (!StringUtils.isEmpty(order)) {
            //  进行分割
            String[] split = order.split(":");
            //  声明一个排序字段
            String field = "";
            //  判断
            if (null != split && split.length == 2) {
                //  split[0]; // 1,2,3
                //  split[1]; // desc 或 asc
                switch (split[0]) {
                    case "1":
                        field = "hotScore";
                        break;
                    case "2":
                        field = "playStatNum";
                        break;
                    case "3":
                        field = "createTime";
                        break;
                }
                //  根据条件设置排序规则
                String finalField = field;
                searchRequest.sort(s -> s.field(f -> f.field(finalField).order("asc".equals(SortOrder.Asc) ? SortOrder.Asc : SortOrder.Desc)));
            }
        } else {
            //  默认排序规则
            //  searchRequest.sort(s -> s.field(f -> f.field("hotScore").order(SortOrder.Desc)));
        }
        //  分页：
        Integer from = (albumIndexQuery.getPageNo() - 1) * albumIndexQuery.getPageSize();
        searchRequest.from(from);
        searchRequest.size(albumIndexQuery.getPageSize());
        //  需要将dsl 语句 打印到控制台上去.
        SearchRequest searchRequest1 = searchRequest.build();
        System.out.println("dsl:\t" + searchRequest1.toString());
        //  返回 searchRequest
        return searchRequest1;
    }

    @Override
    public void lowerAlbum(Long albumId) {
        //  删除数据
        this.albumIndexRepository.deleteById(albumId);
    }

    @Override
    public void upperAlbum(Long albumId) {
        //  给封装好的对象赋值。
        AlbumInfoIndex albumInfoIndex = new AlbumInfoIndex();
        //  异步编排 获取专辑对象
        CompletableFuture<AlbumInfo> albumInfoCompletableFuture = CompletableFuture.supplyAsync(() -> {
            //  远程调用获取数据
            Result<AlbumInfo> albumInfoResult = albumInfoFeignClient.getAlbumInfo(albumId);
            //  调用断言判断albumInfoResult
            Assert.notNull(albumInfoResult, "专辑返回结果集为空");
            AlbumInfo albumInfo = albumInfoResult.getData();
            Assert.notNull(albumInfo, "专辑对象为空");
            //  属性拷贝：
            BeanUtils.copyProperties(albumInfo, albumInfoIndex);
            //  返回专辑对象
            return albumInfo;
        }, threadPoolExecutor);
        //  获取主播信息：
        CompletableFuture<Void> userCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            //  远程调用获取数据
            Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVo(albumInfo.getUserId());
            Assert.notNull(userInfoVoResult, "用户返回结果集为空");
            UserInfoVo userInfoVo = userInfoVoResult.getData();
            Assert.notNull(userInfoVo, "用户对象为空");

            albumInfoIndex.setAnnouncerName(userInfoVo.getNickname());
        }, threadPoolExecutor);

        //  获取分类数据
        CompletableFuture<Void> categoryCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            //  获取分类数据
            Result<BaseCategoryView> categoryViewResult = categoryFeignClient.getCategoryView(albumInfo.getCategory3Id());
            Assert.notNull(categoryViewResult, "分类返回结果集为空");
            BaseCategoryView baseCategoryView = categoryViewResult.getData();
            Assert.notNull(baseCategoryView, "分类对象为空");
            albumInfoIndex.setCategory1Id(baseCategoryView.getCategory1Id());
            albumInfoIndex.setCategory2Id(baseCategoryView.getCategory2Id());
            albumInfoIndex.setCategory3Id(baseCategoryView.getCategory3Id());
        }, threadPoolExecutor);

        //  获取属性数据
        CompletableFuture<Void> attributeCompletableFuture = CompletableFuture.runAsync(() -> {
            Result<List<AlbumAttributeValue>> result = albumInfoFeignClient.findAlbumAttributeValue(albumId);
            Assert.notNull(result, "专辑属性集合为空");
            List<AlbumAttributeValue> albumAttributeValueList = result.getData();
            Assert.notNull(albumAttributeValueList, "专辑属性对象为空");
            //  从这个集合中获取属性与属性值Id
            List<AttributeValueIndex> attributeValueIndexList = albumAttributeValueList.stream().map(albumAttributeValue -> {
                //  创建对象
                AttributeValueIndex attributeValueIndex = new AttributeValueIndex();
                //  赋值
                attributeValueIndex.setAttributeId(albumAttributeValue.getAttributeId());
                attributeValueIndex.setValueId(albumAttributeValue.getValueId());
                //  返回数据
                return attributeValueIndex;
            }).collect(Collectors.toList());
            //  这个集合泛型 AttributeValueIndex  List<AttributeValueIndex> attributeValueIndexList;
            albumInfoIndex.setAttributeValueIndexList(attributeValueIndexList);
        }, threadPoolExecutor);

        //  给统计数据进行赋值.
        int playStatNum = new Random().nextInt(100000000);
        int subscribeStatNum = new Random().nextInt(10000);
        int buyStatNum = new Random().nextInt(300000000);
        int commentStatNum = new Random().nextInt(900000000);

        albumInfoIndex.setPlayStatNum(playStatNum);
        albumInfoIndex.setSubscribeStatNum(subscribeStatNum);
        albumInfoIndex.setBuyStatNum(buyStatNum);
        albumInfoIndex.setCommentStatNum(commentStatNum);
        //  热度排名
        double hotScore = new Random().nextInt(1000000);
        albumInfoIndex.setHotScore(hotScore);
        //  这个四个线程必须都要执行完成之后，在统一保存！
        CompletableFuture.allOf(albumInfoCompletableFuture, userCompletableFuture, categoryCompletableFuture, attributeCompletableFuture).join();
        //  专辑上架
        this.albumIndexRepository.save(albumInfoIndex);

        //  给提词库赋值：
        //  专辑标题提词
        SuggestIndex suggestIndex = new SuggestIndex();
        //  赋值Id
        suggestIndex.setId(UUID.randomUUID().toString().replaceAll("-",""));
        //  赋值关键词
        suggestIndex.setKeyword(new Completion(new String[]{albumInfoIndex.getAlbumTitle()}));
        //  赋值拼音
        suggestIndex.setKeywordPinyin(new Completion(new String[]{PinYinUtils.toHanyuPinyin(albumInfoIndex.getAlbumTitle())}));
        //  赋值首字母
        suggestIndex.setKeywordSequence(new Completion(new String[]{PinYinUtils.getFirstLetter(albumInfoIndex.getAlbumTitle())}));
        //  保存数据
        suggestIndexRepository.save(suggestIndex);

        //  专辑简介：
        SuggestIndex albumIntroSuggestIndex = new SuggestIndex();
        //  赋值Id
        albumIntroSuggestIndex.setId(UUID.randomUUID().toString().replaceAll("-",""));
        //  赋值关键词
        albumIntroSuggestIndex.setKeyword(new Completion(new String[]{albumInfoIndex.getAlbumIntro()}));
        //  赋值拼音
        albumIntroSuggestIndex.setKeywordPinyin(new Completion(new String[]{PinYinUtils.toHanyuPinyin(albumInfoIndex.getAlbumIntro())}));
        //  赋值首字母
        albumIntroSuggestIndex.setKeywordSequence(new Completion(new String[]{PinYinUtils.getFirstLetter(albumInfoIndex.getAlbumIntro())}));
        //  保存数据
        suggestIndexRepository.save(albumIntroSuggestIndex);

        //  将专辑Id 保存到布隆过滤器
        RBloomFilter<Object> bloomFilter = this.redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
        bloomFilter.add(albumId);


    }

    //    @Override
    //    public void upperAlbum(Long albumId) {
    //        //  给封装好的对象赋值。
    //        AlbumInfoIndex albumInfoIndex = new AlbumInfoIndex();
    //        //  远程调用获取数据
    //        Result<AlbumInfo> albumInfoResult = albumInfoFeignClient.getAlbumInfo(albumId);
    //        //  调用断言判断albumInfoResult
    //        Assert.notNull(albumInfoResult,"专辑返回结果集为空");
    //        AlbumInfo albumInfo = albumInfoResult.getData();
    //        Assert.notNull(albumInfo,"专辑对象为空");
    //        albumInfoIndex.setId(albumId);
    //        albumInfoIndex.setAlbumTitle(albumInfo.getAlbumTitle());
    //        albumInfoIndex.setAlbumIntro(albumInfo.getAlbumIntro());
    //        //  获取主播信息
    //        Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVo(albumInfo.getUserId());
    //        Assert.notNull(userInfoVoResult,"用户返回结果集为空");
    //        UserInfoVo userInfoVo = userInfoVoResult.getData();
    //        Assert.notNull(userInfoVo,"用户对象为空");
    //        albumInfoIndex.setAnnouncerName(userInfoVo.getNickname());
    //        albumInfoIndex.setCoverUrl(albumInfo.getCoverUrl());
    //        albumInfoIndex.setIncludeTrackCount(albumInfo.getIncludeTrackCount());
    //        albumInfoIndex.setIsFinished(String.valueOf(albumInfo.getIsFinished()));
    //        albumInfoIndex.setPayType(albumInfo.getPayType());
    //        albumInfoIndex.setCreateTime(albumInfo.getCreateTime());
    //        //  获取分类数据
    //        Result<BaseCategoryView> categoryViewResult = categoryFeignClient.getCategoryView(albumInfo.getCategory3Id());
    //        Assert.notNull(categoryViewResult,"分类返回结果集为空");
    //        BaseCategoryView baseCategoryView = categoryViewResult.getData();
    //        Assert.notNull(baseCategoryView,"分类对象为空");
    //        albumInfoIndex.setCategory1Id(baseCategoryView.getCategory1Id());
    //        albumInfoIndex.setCategory2Id(baseCategoryView.getCategory2Id());
    //        albumInfoIndex.setCategory3Id(baseCategoryView.getCategory3Id());
    //
    //        //  给统计数据进行赋值.
    //        int playStatNum = new Random().nextInt(100000000);
    //        int subscribeStatNum = new Random().nextInt(10000);
    //        int buyStatNum = new Random().nextInt(300000000);
    //        int commentStatNum = new Random().nextInt(900000000);
    //
    //        albumInfoIndex.setPlayStatNum(playStatNum);
    //        albumInfoIndex.setSubscribeStatNum(subscribeStatNum);
    //        albumInfoIndex.setBuyStatNum(buyStatNum);
    //        albumInfoIndex.setCommentStatNum(commentStatNum);
    //        //  热度排名
    //        double hotScore =  new Random().nextInt(1000000);
    //        albumInfoIndex.setHotScore(hotScore);
    //        //  赋值属性值：attributeValueIndexList
    //
    //        Result<List<AlbumAttributeValue>> result = albumInfoFeignClient.findAlbumAttributeValue(albumId);
    //        Assert.notNull(result,"专辑属性集合为空");
    //        List<AlbumAttributeValue> albumAttributeValueList = result.getData();
    //        Assert.notNull(albumAttributeValueList,"专辑属性对象为空");
    //        //  从这个集合中获取属性与属性值Id
    //        List<AttributeValueIndex> attributeValueIndexList = albumAttributeValueList.stream().map(albumAttributeValue -> {
    //            //  创建对象
    //            AttributeValueIndex attributeValueIndex = new AttributeValueIndex();
    //            //  赋值
    //            attributeValueIndex.setAttributeId(albumAttributeValue.getAttributeId());
    //            attributeValueIndex.setValueId(albumAttributeValue.getValueId());
    //            //  返回数据
    //            return attributeValueIndex;
    //        }).collect(Collectors.toList());
    //        //  这个集合泛型 AttributeValueIndex  List<AttributeValueIndex> attributeValueIndexList;
    //        albumInfoIndex.setAttributeValueIndexList(attributeValueIndexList);
    //
    //        //  将albumInfoIndex 对象保存到es中！
    //        albumIndexRepository.save(albumInfoIndex);
    //    }
}
